﻿// <copyright file="Global.asax.cs" company="Clever Software">
// Copyright (c) 2013, 2014 All Right Reserved, http://www.cleversoftware.by
//
// This source is subject to the Microsoft Permissive License.
// Please see the License.txt file for more information.
// All other rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// </copyright>
// <author>Clever Software</author>
// <email>info@cleversoftware.by</email>
// <date>2014-02-04</date> 
// <summary>CleverCMS source code</summary>

namespace CleverCMS.Web
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.IO;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Optimization;
    using System.Web.Routing;

    using log4net;
    using log4net.Appender;
    using log4net.Config;
    using log4net.Repository.Hierarchy;

    using CleverCMS.Web.App_Start;
    using CleverCMS.Core.Web;
    using CleverCMS.Core.Extensions;
    using CleverCMS.Cms.Services.Infrastructure;
    using CleverCMS.Blog.Services.Infrastructure;
    using CleverCMS.Web.Cms.Admin.Controllers;
    using CleverCMS.Core.Infrastructure;

    public class MvcApplication : HttpApplication
    {
        public static void SetAdoNetAppenderConnectionStrings(string connectionStringKey)
        {
            var hier = (Hierarchy)LogManager.GetRepository();
            if (hier != null)
            {
                IEnumerable<AdoNetAppender> appenders = hier.GetAppenders().OfType<AdoNetAppender>();

                foreach (AdoNetAppender appender in appenders)
                {
                    appender.ConnectionString = ConfigurationManager.ConnectionStrings[connectionStringKey].ConnectionString;
                    appender.ActivateOptions();
                }
            }
        }

        protected void Application_Start()
        {
            InitializeLogging();

            SetAdoNetAppenderConnectionStrings("DataContext");

            
            CmsMappingsRegistration.RegisterAll();
            BlogMappingsRegistration.RegisterAll();
            SitemapRegistration.RegisterAll(RouteTable.Routes);

            AreaRegistration.RegisterAllAreas();

            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new CustomRazorViewEngine());

            ControllerBuilder.Current.SetControllerFactory(new CleverCmsControllerFactory());

            InitialiseJobScheduler();
        }

        private static void InitializeLogging()
        {
            var log4NetPath = HttpContext.Current.Server.MapPath("~/log4net.config");
            XmlConfigurator.ConfigureAndWatch(new FileInfo(log4NetPath));
        }

        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            OpenSessionInView();
            SeoRedirects();
        }

        private void OpenSessionInView()
        {
            string path = Context.Request.Url.AbsolutePath;
            if (IgnoreExtension(path))
                return;
        }

        private static bool IgnoreExtension(string path)
        {
            return path.EndsWith(".css", StringComparison.InvariantCultureIgnoreCase) ||
                   path.EndsWith(".js", StringComparison.InvariantCultureIgnoreCase)  ||
                   path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase) ||
                   path.EndsWith(".jpg", StringComparison.InvariantCultureIgnoreCase) ||
                   path.EndsWith(".gif", StringComparison.InvariantCultureIgnoreCase) ||
                   path.EndsWith(".htm", StringComparison.InvariantCultureIgnoreCase);
        }

        private void CloseSessionInView()
        {
            string path = Context.Request.Url.AbsolutePath;
            if (IgnoreExtension(path))
                return;
        }

        protected void Application_EndRequest(object sender, EventArgs e)
        {
            CloseSessionInView();
        }
        
        void Application_Error(object sender, EventArgs e)
        {
            var exception = Server.GetLastError();
            Server.ClearError();

            var log = LogManager.GetLogger(this.GetType());
            log.Error("Error!", exception);

            if (null != Context && null != Context.AllErrors)
                System.Diagnostics.Debug.WriteLine(Context.AllErrors.Length);

            var routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("action", "InternalServerError");
            routeData.Values.Add("statusCode", 500);
            if (exception.GetType() == typeof(HttpException))
            {
                Response.StatusCode = ((HttpException)exception).GetHttpCode();
                switch (Response.StatusCode)
                {
                    case 404:
                        routeData.Values["action"] = "NotFound";
                        routeData.Values["statusCode"] = Response.StatusCode;
                        break;
                }
            }

            IController controller = new ErrorController();
            controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
            Response.End();
        }

        private void SeoRedirects()
        {
            if (Request.HttpMethod.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
                return;

            string absolutePath = HttpContext.Current.Request.Url.AbsolutePath;
            string query = HttpContext.Current.Request.Url.Query;
            string url = HttpContext.Current.Request.Url.ToString();

            if (RemoveDoubleSlashes(absolutePath))
                PermanentRedirect(url.Replace("//", "/") + query);

            if (AddTrailingSlash(absolutePath))
                PermanentRedirect(url + "/" + query);
        }

        public bool RemoveDoubleSlashes(string absolutePath)
        {
            // If we have double-slashes, strip them out
            if (absolutePath.Contains("//"))
                return true;
        
            return false;
        }

        public void PermanentRedirect(string url)
        {
            HttpResponse response = HttpContext.Current.Response;
            response.PermanentRedirect(url);
        }

        public bool AddTrailingSlash(string absolutePath)
        {
            absolutePath = absolutePath.NullSafe();
            return !absolutePath.Contains(".") && !absolutePath.EndsWith("/");
        }

        protected void InitialiseJobScheduler()
        {
            //ISchedulerFactory factory = new StdSchedulerFactory();
            //var scheduler = factory.GetScheduler();
            //scheduler.JobFactory = new JobFactory();
            //scheduler.Start();
        }
    }
}